package com.zdya.combatdocuments.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zdya.combatdocuments.entity.*;
import com.zdya.combatdocuments.entity.dto.ElementDTO;
import com.zdya.combatdocuments.entity.dto.SeatDTO;
import com.zdya.combatdocuments.entity.dto.StageDTO;
import com.zdya.combatdocuments.entity.vo.MindMapVO;
import com.zdya.combatdocuments.entity.vo.XLSMindMapVO;
import com.zdya.combatdocuments.ethereum.EthChain;
import com.zdya.combatdocuments.exception.BusinessException;
import com.zdya.combatdocuments.mapper.*;
import com.zdya.combatdocuments.p2pNetwork.NodeUtil;
import com.zdya.combatdocuments.service.MindMapService;
import com.zdya.combatdocuments.util.AjaxResult;
import com.zdya.combatdocuments.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * * @author: bj
 * * @date: 2023/6/7
 * * @desc: 思维导图实现层
 */
@Slf4j
@Service
public class MindMapServiceImpl implements MindMapService {

    @Autowired
    private NetworkMapper networkMapper;
    @Autowired
    private NodeUtil nodeUtil;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private GradeMapper gradeMapper;
    @Autowired
    private NetworkUserMapper networkUserMapper;

    /**
     * 查询思维导图信息
     * @return
     */
    @Override
    public MindMapVO queryMindMapInfo() {
        MindMapVO mindMapVO = new MindMapVO();
        mindMapVO = this.getMindMap();
        return mindMapVO;
    }

    /**
     * 思维导图导出excel
     * @param response
     */
    @Override
    public void exportMindMap(HttpServletResponse response) {
        MindMapVO mindMapVO = new MindMapVO();
        mindMapVO = this.getMindMap();
        // 获取所有阶段的信息
        List<StageDTO> stages = mindMapVO.getList();
        List<XLSMindMapVO> list = new ArrayList<>();
        XLSMindMapVO xlsMindMapVO = new XLSMindMapVO();
        xlsMindMapVO.setNetName(mindMapVO.getName());// 网络名称
        for (StageDTO stage : stages) {
            xlsMindMapVO.setStage(stage.getName());// 阶段
            for (ElementDTO elementDTO : stage.getList()) {
                xlsMindMapVO.setElement(elementDTO.getName());//要素名
                List<SeatDTO> seats = elementDTO.getList();// 席位
                for (SeatDTO seatDTO : seats) {
                    xlsMindMapVO.setSeat(seatDTO.getName());// 席位名
                    List<Approval> upApprovals = seatDTO.getUpApprovals();// 向上审批流
                    for (Approval approval : upApprovals) {
                        xlsMindMapVO.setName(approval.getName());// 文书名称
                        if ("0".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("已备案");// 文书状态
                        } else if ("1".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("审批中");// 文书状态
                        } else if ("2".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("审批结束");// 文书状态
                        }
                        String level = approval.getLevel()+"";
                        if ("0".equals(level)) {
                            xlsMindMapVO.setDocGrade("急");// 文书等级
                        } else if("1".equals(level)) {
                            xlsMindMapVO.setDocGrade("加急");// 文书等级
                        } else if("2".equals(level)) {
                            xlsMindMapVO.setDocGrade("特急");// 文书等级
                        }
                        xlsMindMapVO.setDocType("向上");
                        xlsMindMapVO.setSender(approval.getSender());//文书发起人
                        if (Objects.isNull(approval.getList())) {
                            continue;
                        }
                        JSONArray objects = new JSONArray(approval.getList());
                        List<Sign> signs = JSONUtil.toList(objects, Sign.class);
                        for (Sign sign : signs) {
                            // 审批流
                            XLSMindMapVO newInsert = new XLSMindMapVO();
                            newInsert.setNetName(xlsMindMapVO.getNetName());// 网络名称
                            newInsert.setStage(xlsMindMapVO.getStage());// 阶段
                            newInsert.setElement(xlsMindMapVO.getElement());//要素名
                            newInsert.setSeat(xlsMindMapVO.getSeat());// 席位名
                            newInsert.setName(xlsMindMapVO.getName());// 文书名称
                            newInsert.setStatus(xlsMindMapVO.getStatus());// 文书状态
                            newInsert.setDocType(xlsMindMapVO.getDocType());// 文书类别
                            newInsert.setSender(xlsMindMapVO.getSender());//发起人
                            newInsert.setDocGrade(xlsMindMapVO.getDocGrade());// 文书等级
                            newInsert.setApproveName(sign.getName());//审批人
                            newInsert.setTime(DateUtil.format(new Date(sign.getTime()), "yyyy-MM-dd HH:mm:ss"));// 审批时间
                            if (sign.isTimeout()) {
                                newInsert.setTimeout("已超时");// 是否超时
                            } else {
                                newInsert.setTimeout("未超时");// 是否超时
                            }
                            list.add(newInsert);
                        }
                    }
                    List<Approval> downApprovals = seatDTO.getDownApprovals();// 向下审批流
                    for (Approval approval : downApprovals) {
                        xlsMindMapVO.setName(approval.getName());// 文书名称
                        if ("0".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("已备案");// 文书状态
                        } else if ("1".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("审批中");// 文书状态
                        } else if ("2".equals(approval.getStatus())) {
                            xlsMindMapVO.setStatus("审批结束");// 文书状态
                        }
                        String level = approval.getLevel()+"";
                        if ("0".equals(level)) {
                            xlsMindMapVO.setDocGrade("急");// 文书等级
                        } else if("1".equals(level)) {
                            xlsMindMapVO.setDocGrade("加急");// 文书等级
                        } else if("2".equals(level)) {
                            xlsMindMapVO.setDocGrade("特急");// 文书等级
                        }
                        xlsMindMapVO.setDocType("向下");//文书类别
                        xlsMindMapVO.setSender(approval.getSender());//文书发起人
                        if (Objects.isNull(approval.getList())) {
                            continue;
                        }
                        JSONArray objects = new JSONArray(approval.getList());
                        List<Sign> signs = JSONUtil.toList(objects, Sign.class);
                        for (Sign sign : signs) {
                            // 审批流
                            XLSMindMapVO newInsert = new XLSMindMapVO();
                            newInsert.setNetName(xlsMindMapVO.getNetName());// 网络名称
                            newInsert.setStage(xlsMindMapVO.getStage());// 阶段
                            newInsert.setElement(xlsMindMapVO.getElement());//要素名
                            newInsert.setSeat(xlsMindMapVO.getSeat());// 席位名
                            newInsert.setName(xlsMindMapVO.getName());// 文书名称
                            newInsert.setStatus(xlsMindMapVO.getStatus());// 文书状态
                            newInsert.setDocGrade(xlsMindMapVO.getDocGrade());// 文书等级
                            newInsert.setDocType(xlsMindMapVO.getDocType());// 文书类别
                            newInsert.setSender(xlsMindMapVO.getSender());//发起人
                            newInsert.setDocGrade(xlsMindMapVO.getDocGrade());// 文书等级
                            newInsert.setApproveName(sign.getName());//审批人
                            newInsert.setTime(DateUtil.format(new Date(sign.getTime()), "yyyy-MM-dd HH:mm:ss"));// 审批时间
                            if (sign.isTimeout()) {
                                newInsert.setTimeout("已超时");// 是否超时
                            } else {
                                newInsert.setTimeout("未超时");// 是否超时
                            }
                            list.add(newInsert);
                        }
                    }
                }
            }
        }
        String fileName = nodeUtil.getLocalUser().getName() + "_" + IdUtil.fastSimpleUUID();
        ExcelUtil.writeExcelOneSheet(response, fileName, "作战审批记录", list);
    }

    private MindMapVO getMindMap() {
        MindMapVO mindMapVO = new MindMapVO();
        // 判断当前网络是否存在
        Long networkId = nodeUtil.getNetworkId();
        Network network = null;
        try {
            network = networkMapper.selectById(networkId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("网络信息异常！");
        }
        if (Objects.isNull(network)) {
            throw new BusinessException("当前网络不存在！");
        }
        // 按照阶段，存储文书审批信息
        Map<String,List<Approval>> list1 = new HashMap<>();
        // 查询当前网络所有阶段
        LambdaQueryWrapper<Grade> gradeWrapper = new LambdaQueryWrapper<>();
        gradeWrapper.eq(Grade::getNetworkId, networkId);
        List<Grade> grades = gradeMapper.selectList(gradeWrapper);

        List<ChainData> chainDataList = nodeUtil.getChainDataList();
        for (ChainData chainData : chainDataList) {
            if (Objects.isNull(chainData.getSerialNum())) {
                continue;
            }
            Approval approval = new Approval();
            String sender = chainData.getSender();//发起者
            if (StrUtil.isEmpty(sender) || "null".equals(sender)) {
                continue;
            }
            String name = chainData.getOriginalFileName();//文书名
            String sendTime = chainData.getSendTime()+"";//发起时间
            String status = chainData.getStatus()+"";//文书状态
            String level = chainData.getLevel();//文书等级
            String docType = chainData.getType()+"";//文书类别 0 向上 1 向下
            // 判断当前审批发起是在第几阶段
            String stage = (grades.size()) + ""; // 当前阶段 1代表第一阶段 2 代表第二阶段
            Long aLong = Long.valueOf(sendTime);
            long lSendTime = aLong.longValue();
            int index = 0;
            for (Grade grade : grades) {
                index++;
                if (lSendTime > grade.getGradeTime().longValue()) {
                    continue;
                } else {
                    stage = index+"";
                    break;
                }
            }
            String signs = chainData.getSigns();
            List<Sign> list = null;
            if (StrUtil.isNotBlank(signs)) {
                list = JSONUtil.parseArray(signs).toList(Sign.class);// 审批流
            }
            approval.setName(name);
            approval.setSender(sender);
            approval.setTime(Long.valueOf(sendTime));
            approval.setStatus(status);
            approval.setLevel(level);
            approval.setDocType(docType);
            approval.setStage(stage);
            approval.setList(list);
            List<Approval> approvals = list1.get(stage);
            if(approvals!=null){
                approvals.add(approval);
            }else{
                approvals = new ArrayList<>();
                approvals.add(approval);
                list1.put(stage,approvals);
            }
        }

        List<StageDTO> stageDTOS = new ArrayList<>();//阶段
        Set<String> strings = list1.keySet();
        for (String str : strings){
            List<Approval> approvals = list1.get(str);
            StageDTO stageDTO = makeDate(str,approvals);
            stageDTOS.add(stageDTO);
        }
        for (StageDTO stageDTO : stageDTOS){
            List<ElementDTO> list2 = stageDTO.getList();
            for (ElementDTO elementDTO : list2){
                List<SeatDTO> list3 = elementDTO.getList();
                for (SeatDTO seatDTO :list3){
                    List<Approval> upApprovals = seatDTO.getUpApprovals();
                    for (Approval approval :upApprovals){
                        LambdaQueryWrapper<User> wrapperUser = new LambdaQueryWrapper<>();
                        wrapperUser.eq(User::getUsername, approval.getSender());// 账号
                        User userInfo = userMapper.selectOne(wrapperUser);
                        approval.setSender(userInfo.getName());
                        approval.setName(bulidFileName(approval.getName()));
                    }
                    List<Approval> downApprovals = seatDTO.getDownApprovals();
                    for (Approval approval :downApprovals){
                        LambdaQueryWrapper<User> wrapperUser = new LambdaQueryWrapper<>();
                        wrapperUser.eq(User::getUsername, approval.getSender());// 账号
                        User userInfo = userMapper.selectOne(wrapperUser);
                        approval.setSender(userInfo.getName());
                        approval.setName(bulidFileName(approval.getName()));
                    }
                }
            }
        }

        // 查询当前网络所有要素
        mindMapVO.setName(network.getName());//网络名称
        mindMapVO.setList(stageDTOS);// 阶段
        return mindMapVO;
    }

    public static JSONObject getAllData(String chainid , String contractAddress ){
        try {
            AjaxResult keyListLengthByChain = EthChain.getKeyListLengthByChain(chainid, contractAddress);
            String leng = keyListLengthByChain.getData().toString();
            int size = Integer.valueOf(leng);
            List<String> keyList = new ArrayList<>();

            for (int i = 0; i < size; i++) {
                try {
                    AjaxResult keyByChain = EthChain.getKeyByChain(chainid, contractAddress, i + "");
                    keyList.add(keyByChain.getData().toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            JSONObject json = new JSONObject();

            for (String key : keyList){
                try {
                    AjaxResult dataByChain = EthChain.getDataByChain(chainid, contractAddress, "", "", key);
                    json.put(key,dataByChain.getData());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return json;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONObject();
    }

    public StageDTO makeDate(String key,List<Approval> list){
        // 查询当前网络下的所有用户id
        Long networkId = nodeUtil.getNetworkId();
        LambdaQueryWrapper<NetworkUser> networkUserWrapper = new LambdaQueryWrapper<>();
        networkUserWrapper.select(NetworkUser::getUserId);
        networkUserWrapper.eq(NetworkUser::getNetworkId, networkId);
        List<NetworkUser> networkUsers = networkUserMapper.selectList(networkUserWrapper);
        List<Long> userIds = new ArrayList<>();
        for (NetworkUser networkUser : networkUsers) {
            userIds.add(networkUser.getUserId());
        }
        
        // 查询当前网络用户下所有要素
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.select(User::getElement);
        userWrapper.ne(User::getUsername, "admin");
        userWrapper.in(User::getId, userIds);
        userWrapper.groupBy(User::getElement);
        List<User> allEle = userMapper.selectList(userWrapper);
        // 按照阶段分组
        List<String> strings = new ArrayList<>();
        for (Approval approval : list) {
            String stage = approval.getStage();
            strings.add(stage);
        }
        StageDTO stageDTO = new StageDTO();
        LambdaQueryWrapper<Grade> wrapperG = new LambdaQueryWrapper<>();
        wrapperG.eq(Grade::getNetworkId, nodeUtil.getNetworkId());
        Integer stage = Integer.valueOf(strings.get(0));

        List<Grade> grades = gradeMapper.selectList(wrapperG);
        Grade grade = grades.get(stage - 1);
        stageDTO.setGradeTime(DateUtil.format(new Date(grade.getGradeTime()), "yyyy-MM-dd HH:mm:ss"));
        stageDTO.setName(grade.getGradeName());//阶段
        List<ElementDTO> elementDTOS = new ArrayList<>();
        for (User u : allEle) {
            ElementDTO elementDTO = new ElementDTO();
            elementDTO.setName(u.getElement());
            // 查询每个要素下的席位
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(User::getSeat);
            wrapper.eq(User::getElement, u.getElement());
            wrapper.groupBy(User::getSeat);
            List<User> users = userMapper.selectList(wrapper);
            List<SeatDTO> seatDTOS = new ArrayList<>();
            for (User uSeat : users) {
                SeatDTO seatDTO = new SeatDTO();
                seatDTO.setName(uSeat.getSeat());
                List<Approval> upApprovals = new ArrayList<>();
                List<Approval> downApprovals = new ArrayList<>();
                for (Approval approval : list) {
                    String sender = approval.getSender();
                    LambdaQueryWrapper<User> wrapperUser = new LambdaQueryWrapper<>();
                    wrapperUser.eq(User::getUsername, sender);// 账号
                    User userInfo = userMapper.selectOne(wrapperUser);
                    if((userInfo.getSeat()).equals(seatDTO.getName())){
                        if((userInfo.getElement()).equals(elementDTO.getName())){
                            String docType = approval.getDocType();
                            if ("0".equals(docType)) {// 向上
                                upApprovals.add(approval);
                            } else {
                                downApprovals.add(approval);
                            }
                        }
                    }
                }
                if(upApprovals != null){
                    seatDTO.setUpApprovals(upApprovals);
                }
                if (downApprovals != null){
                    seatDTO.setDownApprovals(downApprovals);
                }
                seatDTOS.add(seatDTO);
            }
            elementDTO.setList(seatDTOS);
            elementDTOS.add(elementDTO);// 要素
        }
        stageDTO.setList(elementDTOS);
        return stageDTO;
    }


    public String bulidFileName(String name){
        if(name!=null&&!"".equals(name)) {
            name = name.replaceAll(".pdf", "").replaceAll(".PDF", "");
            name = "《" + name + "》";
            return name;
        }else{
            return "";
        }
    }

}
